#include "songdisplay.h"
#include <QPainter>
#include "const.h"
#include "functions.h"
#include <fstream>
#include <iostream>

SongDisplay::SongDisplay(QWidget* parent) : QWidget(parent)
{
  lineCount = 0;
  updateTimer = new QTimer(this);
  newNotes = new QTimer(this);
  std::string songfile = "test";
  song = new std::ifstream(songfile.c_str());
  songinfo = LoadSong(*song);
  connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateNotes()));
  connect(newNotes, SIGNAL(timeout()), this, SLOT(getNotes()));
  connect(this, SIGNAL(notesUpdated()), this, SLOT(update()));
  int updatetime = 1000 / (songinfo.bpm / 60);
  updateTimer->start(updatetime / c_numupdates);
  newNotes->start(updatetime);

  for (int i = 0; i < 5; ++i)
    keys[i] = false;
}

SongDisplay::~SongDisplay()
{
}


void SongDisplay::addNote(Note note)
{
  notes.push_back(note);
}

void SongDisplay::paintEvent(QPaintEvent *)
{
  QPainter painter(this);
  painter.drawImage(QPoint(0, 0), QImage("background.bmp"));
  painter.setPen(Qt::NoPen);
  painter.setBrush(Qt::black);
  painter.drawRect(QRect(0, c_endy, 600, 1));
  for (std::vector<Note>::iterator it = notes.begin(); it != notes.end(); ++it)
    {
      int column = it->getColumn();
      int x = c_startx + (column - 1) * (c_width + c_hspacing);
      int y = it->getY();
      NOTE_TYPE type = it->getType();
      painter.setBrush(c_colors[column - 1]);
      if (it->getIncorrect())
	painter.setBrush(Qt::black);
      if (type != CONT)
	painter.drawRect(QRect(x, y, c_width, c_height));
      if (type != INDIV)
	{
	  int height = MIN(c_vspacing, y - c_starty);
	  int drawy = y - height;
	  height = MIN(height, c_endy - drawy);
	  painter.drawRect(QRect(x + (c_width - c_held_width) / 2, drawy, c_held_width, height));
	}
    }
}

void SongDisplay::getNotes()
{
  //First, have an array of five characters
  //Next, pass this array, along with songfile, to GetLine
  //Next, interpret these five characters, create a note based on the character
  //For example, if it's 'n', the second parameter is false
  //If it's '.', don't create a note at all
  //Then, you add these notes via notes.push_back(/*note name*/);
  if (lineCount++ < songinfo.numLines)
    {
      char noteLine[5];
      GetLine(*song, noteLine);
      for (int i = 0; i < 5; ++i)
	{
	  NOTE_TYPE type = CONT;
	  switch (noteLine[i])
	    {
	    case 'h': type = HELD;
	      break;
	    case 'c': type = CONT;
	      break;
	    case 'n': type = INDIV;
	    }
	  if (noteLine[i] != '.')
	    {
	      Note next(i + 1, type);
	      addNote(next);
	    }
	}
    }
}

void SongDisplay::updateNotes()
{
  //This whole section is a horrible, horrible, horrible hack
  //I really hate iterators.
  std::vector<Note>::iterator it = notes.begin();
  while(it != notes.end())
    {
      it->moveNote();
      if (it->outOfRange())
	while (it != notes.end())
	  if (it->outOfRange())
	    {
	      it = notes.erase(it);
	      it->moveNote();
	    }
	  else
	    break;
      else
	++it;
    }
  emit notesUpdated();
}

//GetLine(songfile, asdfasdf);
void SongDisplay::keyPressEvent( QKeyEvent * event )
{ 
  switch (event->key()) 
    {
    case Qt::Key_F1:
      keys[0]=true;
      break;
    case Qt::Key_F2:
      keys[1]=true;
      break;
    case Qt::Key_F3:
      keys[2]=true;
      break;
    case Qt::Key_F4:
      keys[3]=true;
      break;
    case Qt::Key_F5:
      keys[4]=true;
    case Qt::Key_Enter:
    case Qt::Key_Return:
    case Qt::Key_Shift: processKeys();
    }
}

void SongDisplay::keyReleaseEvent(QKeyEvent * event)
{
  switch (event->key())
    {
    case Qt::Key_F1:
      keys[0]=false;
      break;
    case Qt::Key_F2:
      keys[1]=false;
      break;
    case Qt::Key_F3:
      keys[2]=false;
      break;
    case Qt::Key_F4:
      keys[3]=false;
      break;
    case Qt::Key_F5:
      keys[4]=false;
      break;
    }
  processKeys(true);
}	

void SongDisplay::processKeys(bool held)
{
  for (std::vector<Note>::iterator it = notes.begin(); it != notes.end(); ++it)
    {
      if (it->getType() == INDIV && held)
	continue;
      if (!keys[it->getColumn() - 1] && it->getActive())
	{
	  it->setIncorrect();
	}
    }
}
